﻿
'TODO: Document Size Control
''' <summary>
''' This class is used to enable run-time sizing of controls. Set the design surface as the parent control on
''' your form that will contain all the controls you want to be allow user to resize at run-time.
''' To have a control at runtime become user resizeable, simply set the BoundControl of this class to the control
''' you want.
''' </summary>
''' <remarks></remarks>
Public Class SizeControl
#Region "Private Attributes"
    Private _BoundControl As Control
    Private _DesignSurface As Control
    Private _BoundControlDockStyle As System.Windows.Forms.DockStyle

    'Sizing Glyphs
    Private _SizingGlyphs As New List(Of Label)
    Private _OuterFrameRect As Rectangle
    Private _TopLeftRect As Rectangle
    Private _MiddleLeftRect As Rectangle
    Private _BottomLeftRect As Rectangle
    Private _TopCenterRect As Rectangle
    Private _BottomCenterRect As Rectangle
    Private _TopRightRect As Rectangle
    Private _MiddleRightRect As Rectangle
    Private _BottomRightRect As Rectangle

    Private _TopLeftBox As New Label
    Private _MiddleLeftBox As New Label
    Private _BottomLeftBox As New Label
    Private _TopCenterBox As New Label
    Private _BottomCenterBox As New Label
    Private _TopRightBox As New Label
    Private _MiddleRightBox As New Label
    Private _BottomRightBox As New Label

    Private _SizingGlyphsSize As Integer = 7

    'Move/Resize Properties
    Private _IsResizing As Boolean = False
    Private _ResizeStartMouseLocation As Point = Nothing
    Private _ResizeStartCtlLocation As Point = Nothing
    Private _ResizeStartCtlSize As Size = Nothing
    Private _CurrSizeGlyph As ResizeGlyph = ResizeGlyph.None

    Private _DesignerControls As List(Of SnapControl)
    Private _ProximitySnap As Integer = 4

    Private Enum ResizeGlyph As Integer
        None = -1
        TopLeft = 0
        MiddleLeft = 1
        BottomLeft = 2
        TopCenter = 3
        BottomCenter = 4
        TopRight = 5
        MiddleRight = 6
        BottomRight = 7
    End Enum
    Private Enum ClosestPointsX As Integer
        LeftLeft = 0
        LeftRight = 1
        RightLeft = 2
        RightRight = 3
    End Enum
    Private Enum ClosestPointsY As Integer
        TopTop = 0
        TopBottom = 1
        BottomTop = 2
        BottomBottom = 3
    End Enum
    Private Enum MovingEdge As Integer
        None = 0
        LeftEdge = 1
        RightEdge = 2
        TopEdge = 3
        BottomEdge = 4
    End Enum
#End Region

#Region "Public interface"
    ''' <summary>
    ''' Creates a new run-time sizing control. The sizing control does not become "active" on the design surface at run-time
    ''' until it has been bound to the control that needs to be sized. (Using the BoundControl property).
    ''' </summary>
    ''' <param name="DesignSurface"></param>
    ''' <remarks></remarks>
    Public Sub New(ByVal DesignSurface As Control)
        ' Add any initialization after the InitializeComponent() call.
        _SizingGlyphs.Add(_TopLeftBox)
        _SizingGlyphs.Add(_MiddleLeftBox)
        _SizingGlyphs.Add(_BottomLeftBox)
        _SizingGlyphs.Add(_TopCenterBox)
        _SizingGlyphs.Add(_BottomCenterBox)
        _SizingGlyphs.Add(_TopRightBox)
        _SizingGlyphs.Add(_MiddleRightBox)
        _SizingGlyphs.Add(_BottomRightBox)

        For Each glyph As Label In _SizingGlyphs
            AddHandler glyph.MouseEnter, AddressOf MouseEnter_SizeGlyph
            AddHandler glyph.MouseLeave, AddressOf MouseLeave_SizeGlyph
            AddHandler glyph.MouseDown, AddressOf MouseDown_SizeGlyph
            AddHandler glyph.MouseUp, AddressOf MouseUp_SizeGlyph
            AddHandler glyph.MouseMove, AddressOf MouseMove_SizeGlyph
        Next
        _DesignSurface = DesignSurface
    End Sub

    ''' <summary>
    ''' Returns the Design Surface this Sizing control has been bound to. All Sizing operations will be performed within the
    ''' Design surface context (or child container if sized control is parented to an inner control of the Design Surface control).
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property DesignSurface() As Control
        Get
            Return _DesignSurface
        End Get
    End Property

    ''' <summary>
    ''' Used to set which control should become sizeable. Set this value to nothing to "turn off" sizing functionality or set to
    ''' a new control to enabled sizing functionality for that control.
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property BoundControl() As Control
        Get
            Return _BoundControl
        End Get
        Set(ByVal value As Control)
            If value Is Nothing Then
                'Turn off this move control
                RemoveGlyphsFromSurface()
                If _BoundControl IsNot Nothing Then
                    RemoveHandler _BoundControl.LocationChanged, AddressOf ControlLocationChanged
                    RemoveHandler _BoundControl.SizeChanged, AddressOf ControlSizeChanged
                End If
                _BoundControl = Nothing
            Else
                If _BoundControl Is Nothing Then
                    'Binding a control for first time
                    _BoundControlDockStyle = value.Dock
                    AddGlyphsToSurface()
                    AddHandler value.LocationChanged, AddressOf ControlLocationChanged
                    AddHandler value.SizeChanged, AddressOf ControlSizeChanged
                ElseIf _BoundControl IsNot value Then
                    'Binding to a new control
                    RemoveHandler _BoundControl.LocationChanged, AddressOf ControlLocationChanged
                    _BoundControlDockStyle = value.Dock
                    AddGlyphsToSurface()
                    AddHandler value.LocationChanged, AddressOf ControlLocationChanged
                    AddHandler value.SizeChanged, AddressOf ControlSizeChanged
                Else
                    'Binding to same control again
                    RemoveHandler _BoundControl.LocationChanged, AddressOf ControlLocationChanged
                    RemoveHandler _BoundControl.SizeChanged, AddressOf ControlSizeChanged
                    AddGlyphsToSurface()
                    AddHandler value.LocationChanged, AddressOf ControlLocationChanged
                    AddHandler value.SizeChanged, AddressOf ControlSizeChanged
                End If
                _BoundControl = value
                value.BringToFront()
                DrawLayoutGlyphs(False, Nothing, Nothing, False, Nothing, Nothing)
            End If

        End Set
    End Property

    ''' <summary>
    ''' Used to set proximity snapping. Set to 0 to turn proximity snapping off.
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property ProximitySnapSize() As Integer
        Get
            Return _ProximitySnap
        End Get
        Set(ByVal value As Integer)
            _ProximitySnap = value
        End Set
    End Property


    ''' <summary>
    ''' Used to set the size of the sizing glyphs.
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property SizingGlyphsSize() As Integer
        Get
            Return _SizingGlyphsSize
        End Get
        Set(ByVal value As Integer)
            _SizingGlyphsSize = value
            DrawLayoutGlyphs(False, Nothing, Nothing, False, Nothing, Nothing)
        End Set
    End Property
#End Region

#Region "Private Methods"
    Private Sub CalculateAllBounds()
        'Outer Frame

        _OuterFrameRect = _DesignSurface.RectangleToClient(_BoundControl.Parent.RectangleToScreen(_BoundControl.Bounds))

        'Corner Coordinates
        Dim TopLeft As Point = New Point(_OuterFrameRect.X - _SizingGlyphsSize \ 2, _OuterFrameRect.Y - _SizingGlyphsSize \ 2)
        Dim BottomLeft As Point = New Point(_OuterFrameRect.X - _SizingGlyphsSize \ 2, _OuterFrameRect.Y + _OuterFrameRect.Height - _SizingGlyphsSize \ 2)
        Dim TopRight As Point = New Point(_OuterFrameRect.X + _OuterFrameRect.Width - _SizingGlyphsSize \ 2, TopLeft.Y)
        Dim BottomRight As Point = New Point(TopRight.X, BottomLeft.Y)
        Dim MiddleY As Integer = _OuterFrameRect.Y + _OuterFrameRect.Height \ 2
        Dim CenterX As Integer = _OuterFrameRect.X + _OuterFrameRect.Width \ 2

        'Top Left
        _TopLeftRect = New Rectangle(TopLeft.X, TopLeft.Y, _SizingGlyphsSize, _SizingGlyphsSize)

        'Middle Left
        _MiddleLeftRect = New Rectangle(TopLeft.X, MiddleY - _SizingGlyphsSize \ 2, _SizingGlyphsSize, _SizingGlyphsSize)

        'Bottom Left
        _BottomLeftRect = New Rectangle(BottomLeft.X, BottomLeft.Y, _SizingGlyphsSize, _SizingGlyphsSize)

        'Top Center
        _TopCenterRect = New Rectangle(CenterX - _SizingGlyphsSize \ 2, TopLeft.Y, _SizingGlyphsSize, _SizingGlyphsSize)

        'Bottom Center
        _BottomCenterRect = New Rectangle(CenterX - _SizingGlyphsSize \ 2, BottomLeft.Y, _SizingGlyphsSize, _SizingGlyphsSize)

        'Top Right
        _TopRightRect = New Rectangle(TopRight.X, TopRight.Y, _SizingGlyphsSize, _SizingGlyphsSize)

        'Middle Right
        _MiddleRightRect = New Rectangle(TopRight.X, MiddleY - _SizingGlyphsSize \ 2, _SizingGlyphsSize, _SizingGlyphsSize)

        'Bottom Right
        _BottomRightRect = New Rectangle(BottomRight.X, BottomRight.Y, _SizingGlyphsSize, _SizingGlyphsSize)
    End Sub

    Private Sub AddGlyphsToSurface()
        RemoveGlyphsFromSurface()
        Select Case _BoundControlDockStyle
            Case DockStyle.Bottom
                If Not _DesignSurface.Controls.Contains(_TopCenterBox) Then _DesignSurface.Controls.Add(_TopCenterBox)
            Case DockStyle.Fill
                'No glyphs
            Case DockStyle.Left
                If Not _DesignSurface.Controls.Contains(_MiddleRightBox) Then _DesignSurface.Controls.Add(_MiddleRightBox)
            Case DockStyle.Right
                If Not _DesignSurface.Controls.Contains(_MiddleLeftBox) Then _DesignSurface.Controls.Add(_MiddleLeftBox)
            Case DockStyle.Top
                If Not _DesignSurface.Controls.Contains(_BottomCenterBox) Then _DesignSurface.Controls.Add(_BottomCenterBox)
            Case Else
                If Not _DesignSurface.Controls.Contains(_TopLeftBox) Then _DesignSurface.Controls.Add(_TopLeftBox)
                If Not _DesignSurface.Controls.Contains(_MiddleLeftBox) Then _DesignSurface.Controls.Add(_MiddleLeftBox)
                If Not _DesignSurface.Controls.Contains(_BottomLeftBox) Then _DesignSurface.Controls.Add(_BottomLeftBox)
                If Not _DesignSurface.Controls.Contains(_TopCenterBox) Then _DesignSurface.Controls.Add(_TopCenterBox)
                If Not _DesignSurface.Controls.Contains(_BottomCenterBox) Then _DesignSurface.Controls.Add(_BottomCenterBox)
                If Not _DesignSurface.Controls.Contains(_TopRightBox) Then _DesignSurface.Controls.Add(_TopRightBox)
                If Not _DesignSurface.Controls.Contains(_MiddleRightBox) Then _DesignSurface.Controls.Add(_MiddleRightBox)
                If Not _DesignSurface.Controls.Contains(_BottomRightBox) Then _DesignSurface.Controls.Add(_BottomRightBox)
        End Select
    End Sub
    Private Sub RemoveGlyphsFromSurface()
        If _DesignSurface.Controls.Contains(_TopLeftBox) Then _DesignSurface.Controls.Remove(_TopLeftBox)
        If _DesignSurface.Controls.Contains(_MiddleLeftBox) Then _DesignSurface.Controls.Remove(_MiddleLeftBox)
        If _DesignSurface.Controls.Contains(_BottomLeftBox) Then _DesignSurface.Controls.Remove(_BottomLeftBox)
        If _DesignSurface.Controls.Contains(_TopCenterBox) Then _DesignSurface.Controls.Remove(_TopCenterBox)
        If _DesignSurface.Controls.Contains(_BottomCenterBox) Then _DesignSurface.Controls.Remove(_BottomCenterBox)
        If _DesignSurface.Controls.Contains(_TopRightBox) Then _DesignSurface.Controls.Remove(_TopRightBox)
        If _DesignSurface.Controls.Contains(_MiddleRightBox) Then _DesignSurface.Controls.Remove(_MiddleRightBox)
        If _DesignSurface.Controls.Contains(_BottomRightBox) Then _DesignSurface.Controls.Remove(_BottomRightBox)
    End Sub
    Private Sub BringGlyphsToFront()
        If _DesignSurface.Controls.Contains(_TopLeftBox) Then _TopLeftBox.BringToFront()
        If _DesignSurface.Controls.Contains(_MiddleLeftBox) Then _MiddleLeftBox.BringToFront()
        If _DesignSurface.Controls.Contains(_BottomLeftBox) Then _BottomLeftBox.BringToFront()
        If _DesignSurface.Controls.Contains(_TopCenterBox) Then _TopCenterBox.BringToFront()
        If _DesignSurface.Controls.Contains(_BottomCenterBox) Then _BottomCenterBox.BringToFront()
        If _DesignSurface.Controls.Contains(_TopRightBox) Then _TopRightBox.BringToFront()
        If _DesignSurface.Controls.Contains(_MiddleRightBox) Then _MiddleRightBox.BringToFront()
        If _DesignSurface.Controls.Contains(_BottomRightBox) Then _BottomRightBox.BringToFront()
    End Sub

    Private Sub DrawLayoutGlyphs(ByVal DrawVSnapLine As Boolean, ByVal VSnapLineStart As Point, ByVal VSnapLineEnd As Point, ByVal DrawHSnapLine As Boolean, ByVal HSnapLineStart As Point, ByVal HSnapLineEnd As Point)
        If _BoundControl Is Nothing Then
            'Clear glyphs from drawing surface
            RemoveGlyphsFromSurface()
        Else
            CalculateAllBounds()

            'Top Left
            With _TopLeftBox
                .BackColor = Color.White
                .AutoSize = False
                .BorderStyle = BorderStyle.FixedSingle
                .Location = _TopLeftRect.Location
                .Size = _TopLeftRect.Size
                .BringToFront()
            End With

            'Middle Left
            With _MiddleLeftBox
                .BackColor = Color.White
                .AutoSize = False
                .BorderStyle = BorderStyle.FixedSingle
                .Location = _MiddleLeftRect.Location
                .Size = _MiddleLeftRect.Size
                .BringToFront()
            End With

            'Bottom Left
            With _BottomLeftBox
                .BackColor = Color.White
                .AutoSize = False
                .BorderStyle = BorderStyle.FixedSingle
                .Location = _BottomLeftRect.Location
                .Size = _BottomLeftRect.Size
                .BringToFront()
            End With

            'Top Center
            With _TopCenterBox
                .BackColor = Color.White
                .AutoSize = False
                .BorderStyle = BorderStyle.FixedSingle
                .Location = _TopCenterRect.Location
                .Size = _TopCenterRect.Size
                .BringToFront()
            End With

            'Bottom Center
            With _BottomCenterBox
                .BackColor = Color.White
                .AutoSize = False
                .BorderStyle = BorderStyle.FixedSingle
                .Location = _BottomCenterRect.Location
                .Size = _BottomCenterRect.Size
                .BringToFront()
            End With

            'Top Right
            With _TopRightBox
                .BackColor = Color.White
                .AutoSize = False
                .BorderStyle = BorderStyle.FixedSingle
                .Location = _TopRightRect.Location
                .Size = _TopRightRect.Size
                .BringToFront()
            End With

            'Middle Right
            With _MiddleRightBox
                .BackColor = Color.White
                .AutoSize = False
                .BorderStyle = BorderStyle.FixedSingle
                .Location = _MiddleRightRect.Location
                .Size = _MiddleRightRect.Size
                .BringToFront()
            End With

            'Bottom Right
            With _BottomRightBox
                .BackColor = Color.White
                .AutoSize = False
                .BorderStyle = BorderStyle.FixedSingle
                .Location = _BottomRightRect.Location
                .Size = _BottomRightRect.Size
                .BringToFront()
            End With

            _BoundControl.Refresh()
        End If
    End Sub

    Private Sub FindDesignerControls()
        'Finds other Layout enabled designer controls...
        If _DesignerControls IsNot Nothing Then
            For Each Ctl As SnapControl In _DesignerControls
                Ctl = Nothing
            Next
            _DesignerControls.Clear()
        End If
        _DesignerControls = FindChildControls(_DesignSurface)

    End Sub
    Private Function FindChildControls(ByVal RootControl As Control) As List(Of SnapControl)
        Dim myList As New List(Of SnapControl)

        For Each Ctl As Control In RootControl.Controls
            If Ctl IsNot _BoundControl And Not String.IsNullOrEmpty(Ctl.Name) Then
                myList.Add(New SnapControl(Ctl, Ctl.Parent.PointToScreen(Ctl.Location), Ctl.Size))
                myList.AddRange(FindChildControls(Ctl))
            End If
        Next

        Return myList
    End Function


    Private Function ProximitySnapEdges(ByRef SizeBox As Control, _
                                        ByVal Controls As List(Of SnapControl), _
                                        ByRef VSnapLine As Boolean, _
                                        ByRef VSnapLineStart As Point, _
                                        ByRef VSnapLineEnd As Point, _
                                        ByRef HSnapLine As Boolean, _
                                        ByRef HSnapLineStart As Point, _
                                        ByRef HSnapLineEnd As Point) As Point

        VSnapLine = False
        HSnapLine = False

        Dim LeftEdgeX As Integer = _DesignSurface.PointToScreen(_BoundControl.Location).X
        Dim RightEdgeX As Integer = LeftEdgeX + _BoundControl.Size.Width
        Dim TopEdgeY As Integer = _DesignSurface.PointToScreen(_BoundControl.Location).Y
        Dim BottomEdgeY As Integer = TopEdgeY + _BoundControl.Height

        Dim VMovingEdge As MovingEdge = MovingEdge.None
        Dim HMovingEdge As MovingEdge = MovingEdge.None

        If SizeBox Is _TopLeftBox Then
            VMovingEdge = MovingEdge.LeftEdge
            HMovingEdge = MovingEdge.TopEdge
        ElseIf SizeBox Is _MiddleLeftBox Then
            VMovingEdge = MovingEdge.LeftEdge
            HMovingEdge = MovingEdge.None
        ElseIf SizeBox Is _BottomLeftBox Then
            VMovingEdge = MovingEdge.LeftEdge
            HMovingEdge = MovingEdge.BottomEdge
        ElseIf SizeBox Is _BottomCenterBox Then
            VMovingEdge = MovingEdge.None
            HMovingEdge = MovingEdge.BottomEdge
        ElseIf SizeBox Is _BottomRightBox Then
            VMovingEdge = MovingEdge.RightEdge
            HMovingEdge = MovingEdge.BottomEdge
        ElseIf SizeBox Is _MiddleRightBox Then
            VMovingEdge = MovingEdge.RightEdge
            HMovingEdge = MovingEdge.None
        ElseIf SizeBox Is _TopRightBox Then
            VMovingEdge = MovingEdge.RightEdge
            HMovingEdge = MovingEdge.TopEdge
        ElseIf SizeBox Is _TopCenterBox Then
            VMovingEdge = MovingEdge.None
            HMovingEdge = MovingEdge.TopEdge
        End If



        Dim HSnapCtl As SnapControl = Nothing
        Dim HSnapCtlEdge As MovingEdge = MovingEdge.None
        Dim VSnapCtl As SnapControl = Nothing
        Dim VSnapCtlEdge As MovingEdge = MovingEdge.None

        For Each Ctl As SnapControl In Controls
            Select Case VMovingEdge
                Case MovingEdge.LeftEdge
                    'Compare left edge of bound control to right/left edges of other controls
                Case MovingEdge.RightEdge

                Case Else

            End Select

            Select Case HMovingEdge
                Case MovingEdge.TopEdge

                Case MovingEdge.BottomEdge

                Case Else

            End Select

        Next

        Dim XSnapCtl As SnapControl = Nothing
        Dim YSnapCtl As SnapControl = Nothing

        Dim MinDistX As Integer = Integer.MaxValue
        Dim DistX1 As Integer = 0
        Dim DistX2 As Integer = 0
        If SizeBox Is _MiddleRightBox Then
            'Right Edge moving - Vertical snapping

            For Each Ctl As SnapControl In Controls
                'Compare to left edge of control
                DistX1 = Math.Abs(Ctl.ScreenLoc.X - RightEdgeX)

                'Compare to right edge of control
                DistX2 = Math.Abs(Ctl.ScreenLoc.X + Ctl.Size.Width - RightEdgeX)
                If DistX1 < DistX2 Then
                    'Left edge is closer
                    If DistX1 < MinDistX AndAlso DistX1 < _ProximitySnap Then
                        'Snap to this edge
                        MinDistX = DistX1
                        XSnapCtl = Ctl
                        VSnapLine = True
                    End If
                Else
                    'Right edge is closer

                End If
            Next
        End If
    End Function
    Private Function ProximitySnap(ByVal CurrScreenLoc As Point, _
                                  ByVal CurrSize As Size, _
                                  ByVal Controls As List(Of SnapControl), _
                                  ByRef VSnapLine As Boolean, _
                                  ByRef VSnapLineStart As Point, _
                                  ByRef VSnapLineEnd As Point, _
                                  ByRef HSnapLine As Boolean, _
                                  ByRef HSnapLineStart As Point, _
                                  ByRef HSnapLineEnd As Point) As Point

        Dim SnapPoint As Point = Nothing

        'X Proximity Snapping
        Dim LeftX_LeftX As Integer = 0
        Dim LeftX_RightX As Integer = 0
        Dim RightX_LeftX As Integer = 0
        Dim RightX_RightX As Integer = 0
        Dim ClosestPointX As ClosestPointsX = Nothing
        Dim ClosestDistX As Integer = Integer.MaxValue
        Dim MinClosestDistX As Integer = ClosestDistX
        Dim XSnapCtl As SnapControl = Nothing

        'Y Proximity Snapping
        Dim TopY_TopY As Integer = 0
        Dim TopY_BottomY As Integer = 0
        Dim BottomY_TopY As Integer = 0
        Dim BottomY_BottomY As Integer = 0
        Dim ClosestPointY As ClosestPointsY = Nothing
        Dim ClosestDistY As Integer = Integer.MaxValue
        Dim MinClosestDistY As Integer = ClosestDistY
        Dim YSnapCtl As SnapControl = Nothing

        'Initialize Snap Point to current location
        SnapPoint.X = CurrScreenLoc.X
        SnapPoint.Y = CurrScreenLoc.Y

        VSnapLine = False

        For Each Ctl As SnapControl In Controls
            'X Proximity Snapping
            LeftX_LeftX = Math.Abs(CurrScreenLoc.X - Ctl.ScreenLoc.X)
            If LeftX_LeftX < ClosestDistX Then
                ClosestPointX = ClosestPointsX.LeftLeft
                ClosestDistX = LeftX_LeftX
            End If

            LeftX_RightX = Math.Abs(CurrScreenLoc.X - (Ctl.ScreenLoc.X + Ctl.Size.Width))
            If LeftX_RightX < ClosestDistX Then
                ClosestPointX = ClosestPointsX.LeftRight
                ClosestDistX = LeftX_RightX
            End If

            RightX_LeftX = Math.Abs(Ctl.ScreenLoc.X - (CurrScreenLoc.X + CurrSize.Width))
            If RightX_LeftX < ClosestDistX Then
                ClosestPointX = ClosestPointsX.RightLeft
                ClosestDistX = RightX_LeftX
            End If

            RightX_RightX = Math.Abs(Ctl.ScreenLoc.X + Ctl.Size.Width - (CurrScreenLoc.X + CurrSize.Width))
            If RightX_RightX < ClosestDistX Then
                ClosestPointX = ClosestPointsX.RightRight
                ClosestDistX = RightX_RightX
            End If

            If ClosestDistX < _ProximitySnap AndAlso ClosestDistX < MinClosestDistX Then
                'This is a new closer location that is also within snapping threshold
                VSnapLine = True
                XSnapCtl = Ctl
                'Snap to this X location
                Select Case ClosestPointX
                    Case ClosestPointsX.LeftLeft
                        SnapPoint.X = Ctl.ScreenLoc.X
                    Case ClosestPointsX.LeftRight
                        SnapPoint.X = Ctl.ScreenLoc.X + Ctl.Size.Width
                    Case ClosestPointsX.RightLeft
                        SnapPoint.X = Ctl.ScreenLoc.X - CurrSize.Width
                    Case ClosestPointsX.RightRight
                        SnapPoint.X = Ctl.ScreenLoc.X + Ctl.Size.Width - CurrSize.Width
                End Select
                MinClosestDistX = ClosestDistX
            End If

            'Y Proximity Snapping
            TopY_TopY = Math.Abs(CurrScreenLoc.Y - Ctl.ScreenLoc.Y)
            If TopY_TopY < ClosestDistY Then
                ClosestPointY = ClosestPointsY.TopTop
                ClosestDistY = TopY_TopY
            End If

            TopY_BottomY = Math.Abs(CurrScreenLoc.Y - (Ctl.ScreenLoc.Y + Ctl.Size.Height))
            If TopY_BottomY < ClosestDistY Then
                ClosestPointY = ClosestPointsY.TopBottom
                ClosestDistY = TopY_BottomY
            End If

            BottomY_TopY = Math.Abs(CurrScreenLoc.Y + CurrSize.Height - Ctl.ScreenLoc.Y)
            If BottomY_TopY < ClosestDistY Then
                ClosestPointY = ClosestPointsY.BottomTop
                ClosestDistY = BottomY_TopY
            End If

            BottomY_BottomY = Math.Abs(CurrScreenLoc.Y + CurrSize.Height - (Ctl.ScreenLoc.Y + Ctl.Size.Height))
            If BottomY_BottomY < ClosestDistY Then
                ClosestPointY = ClosestPointsY.BottomBottom
                ClosestDistY = BottomY_BottomY
            End If

            If ClosestDistY < _ProximitySnap AndAlso ClosestDistY < MinClosestDistY Then
                'This is a new closer location that is also within snapping threshold
                HSnapLine = True
                YSnapCtl = Ctl
                'Snap to this Y location
                Select Case ClosestPointY
                    Case ClosestPointsY.TopTop
                        SnapPoint.Y = Ctl.ScreenLoc.Y
                    Case ClosestPointsY.TopBottom
                        SnapPoint.Y = Ctl.ScreenLoc.Y + Ctl.Size.Height
                    Case ClosestPointsY.BottomTop
                        SnapPoint.Y = Ctl.ScreenLoc.Y - CurrSize.Height
                    Case ClosestPointsY.BottomBottom
                        SnapPoint.Y = Ctl.ScreenLoc.Y + Ctl.Size.Height - CurrSize.Height
                End Select
                MinClosestDistY = ClosestDistY
            End If
        Next 'Control


        If VSnapLine Then
            'Snapping along X axis
            Dim X As Integer = 0
            Dim Y1 As Integer = 0
            Dim Y2 As Integer = 0

            If CurrScreenLoc.Y < XSnapCtl.ScreenLoc.Y Then
                'Snapping to Control below
                Y1 = SnapPoint.Y
                Y2 = XSnapCtl.ScreenLoc.Y + XSnapCtl.Size.Height
            Else
                'Snapping to control above
                Y1 = XSnapCtl.ScreenLoc.Y
                Y2 = SnapPoint.Y + CurrSize.Height
            End If

            Select Case ClosestPointX
                Case ClosestPointsX.LeftLeft
                    X = XSnapCtl.ScreenLoc.X - 1
                Case ClosestPointsX.LeftRight
                    X = XSnapCtl.ScreenLoc.X + XSnapCtl.Size.Width
                Case ClosestPointsX.RightLeft
                    X = XSnapCtl.ScreenLoc.X
                Case ClosestPointsX.RightRight
                    X = SnapPoint.X + CurrSize.Width
            End Select

            VSnapLineStart = _DesignSurface.PointToClient(New Point(X, Y1))
            VSnapLineEnd = _DesignSurface.PointToClient(New Point(X, Y2))
        End If

        If HSnapLine Then
            'Snapping along Y axis
            Dim X1 As Integer = 0
            Dim X2 As Integer = 0
            Dim Y As Integer = 0

            If CurrScreenLoc.X < YSnapCtl.ScreenLoc.X Then
                'Snapping to control at right
                X1 = SnapPoint.X
                X2 = YSnapCtl.ScreenLoc.X + YSnapCtl.Size.Width
            Else
                'Snapping to control at left
                X1 = YSnapCtl.ScreenLoc.X
                X2 = SnapPoint.X + CurrSize.Width
            End If

            Select Case ClosestPointY
                Case ClosestPointsY.TopTop
                    Y = YSnapCtl.ScreenLoc.Y - 1
                Case ClosestPointsY.TopBottom
                    Y = YSnapCtl.ScreenLoc.Y + YSnapCtl.Size.Height
                Case ClosestPointsY.BottomTop
                    Y = YSnapCtl.ScreenLoc.Y
                Case ClosestPointsY.BottomBottom
                    Y = YSnapCtl.ScreenLoc.Y + YSnapCtl.Size.Height
            End Select
            HSnapLineStart = _DesignSurface.PointToClient(New Point(X1, Y))
            HSnapLineEnd = _DesignSurface.PointToClient(New Point(X2, Y))
        End If
        Return SnapPoint
    End Function

    Private Class SnapControl
        Private _Ctl As Control
        Private _ScreenLoc As Point
        Private _Size As Size
        Public Sub New(ByVal Ctl As Control, ByVal ScreenLoc As Point, ByVal Size As Size)
            _Ctl = Ctl
            _ScreenLoc = ScreenLoc
            _Size = Size
        End Sub
        Public ReadOnly Property Control() As Control
            Get
                Return _Ctl
            End Get
        End Property
        Public ReadOnly Property ScreenLoc() As Point
            Get
                Return _ScreenLoc
            End Get
        End Property
        Public ReadOnly Property Size() As Size
            Get
                Return _Size
            End Get
        End Property
    End Class

    Private Function FindProximitySnapX(ByVal CurrScreenX As Integer, ByVal Controls As List(Of SnapControl), ByRef SnapOffsetX As Integer, ByRef SnappedCtl As SnapControl) As Boolean
        'See if any Vertical edges are close enough to snap to
        Dim IsSnap As Boolean = False
        Dim LeftDist As Integer = 0
        Dim RightDist As Integer = 0
        For Each ctl As SnapControl In Controls
            'To Left edge
            LeftDist = Math.Abs(ctl.ScreenLoc.X - CurrScreenX)
            If LeftDist < _ProximitySnap AndAlso LeftDist > 0 Then
                'Found one...
                SnapOffsetX = ctl.ScreenLoc.X - CurrScreenX
                SnappedCtl = ctl
                IsSnap = True
                Exit For
            End If
            'To Right Edge
            RightDist = Math.Abs(ctl.ScreenLoc.X + ctl.Size.Width - CurrScreenX)
            If RightDist < _ProximitySnap AndAlso RightDist > 0 Then
                'Found one...
                SnapOffsetX = ctl.ScreenLoc.X + ctl.Size.Width - CurrScreenX
                SnappedCtl = ctl
                IsSnap = True
                Exit For
            End If
        Next
        Return IsSnap
    End Function
    Private Function FindProximitySnapY(ByVal CurrScreenY As Integer, ByVal Controls As List(Of SnapControl), ByRef SnapOffsetY As Integer, ByRef SnappedCtl As SnapControl) As Boolean
        'See if any Horizontal edges are close enough to snap to
        Dim IsSnap As Boolean = False
        Dim TopDist As Integer = 0
        Dim BottomDist As Integer = 0
        For Each ctl As SnapControl In Controls
            'To Top edge
            TopDist = Math.Abs(ctl.ScreenLoc.Y - CurrScreenY)
            If TopDist < _ProximitySnap AndAlso TopDist > 0 Then
                'Found one...
                SnapOffsetY = ctl.ScreenLoc.Y - CurrScreenY
                SnappedCtl = ctl
                IsSnap = True
                Exit For
            End If
            'To Bottom Edge
            BottomDist = Math.Abs(ctl.ScreenLoc.Y + ctl.Size.Height - CurrScreenY)
            If BottomDist < _ProximitySnap AndAlso BottomDist > 0 Then
                'Found one...
                SnapOffsetY = ctl.ScreenLoc.Y + ctl.Size.Height - CurrScreenY
                SnappedCtl = ctl
                IsSnap = True
                Exit For
            End If
        Next
        Return IsSnap
    End Function
#End Region

#Region "Event Handlers Events"
    Private Sub MouseEnter_SizeGlyph(ByVal sender As Object, ByVal e As System.EventArgs)
        'See if mouse is over the Resize glyphs of a control in Layout Mode
        If _BoundControl IsNot Nothing Then
            'There is an Active control
            'If user is not already sizing control, then check to see if they are in the resize glyphs
            'and update cursor/state as needed
            If Not (_IsResizing) Then
                If sender Is _TopLeftBox Then
                    _DesignSurface.Cursor = Cursors.SizeNWSE
                    _CurrSizeGlyph = ResizeGlyph.TopLeft
                ElseIf sender Is _TopCenterBox Then
                    _DesignSurface.Cursor = Cursors.SizeNS
                    _CurrSizeGlyph = ResizeGlyph.TopCenter
                ElseIf sender Is _TopRightBox Then
                    _DesignSurface.Cursor = Cursors.SizeNESW
                    _CurrSizeGlyph = ResizeGlyph.TopRight
                ElseIf sender Is _MiddleRightBox Then
                    _DesignSurface.Cursor = Cursors.SizeWE
                    _CurrSizeGlyph = ResizeGlyph.MiddleRight
                ElseIf sender Is _BottomRightBox Then
                    _DesignSurface.Cursor = Cursors.SizeNWSE
                    _CurrSizeGlyph = ResizeGlyph.BottomRight
                ElseIf sender Is _BottomCenterBox Then
                    _DesignSurface.Cursor = Cursors.SizeNS
                    _CurrSizeGlyph = ResizeGlyph.BottomCenter
                ElseIf sender Is _BottomLeftBox Then
                    _DesignSurface.Cursor = Cursors.SizeNESW
                    _CurrSizeGlyph = ResizeGlyph.BottomLeft
                ElseIf sender Is _MiddleLeftBox Then
                    _DesignSurface.Cursor = Cursors.SizeWE
                    _CurrSizeGlyph = ResizeGlyph.MiddleLeft
                Else
                    _DesignSurface.Cursor = Cursors.Default
                    _CurrSizeGlyph = ResizeGlyph.None
                End If
            End If
        End If
    End Sub
    Private Sub MouseLeave_SizeGlyph(ByVal sender As Object, ByVal e As System.EventArgs)
        'Not in resize area
        _CurrSizeGlyph = ResizeGlyph.None
        _DesignSurface.Cursor = Cursors.Default
    End Sub
    Private Sub MouseDown_SizeGlyph(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
        If e.Button = Windows.Forms.MouseButtons.Left AndAlso _BoundControl IsNot Nothing Then
            _IsResizing = True
            _ResizeStartMouseLocation = _DesignSurface.PointToClient(CType(sender, Control).PointToScreen(e.Location))
            _ResizeStartCtlLocation = _BoundControl.Location
            _ResizeStartCtlSize = _BoundControl.Size
            FindDesignerControls() 'Used for proximity snapping
        End If
    End Sub
    Private Sub MouseUp_SizeGlyph(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
        'If user was resizing then this is now done...
        _IsResizing = False
    End Sub
    Private Sub MouseMove_SizeGlyph(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
        If _BoundControl IsNot Nothing AndAlso _IsResizing Then
            Dim Offset As Point

            Dim VSnapping As Boolean = False
            Dim VSnapLineStart As Point = Nothing
            Dim VSnapLineEnd As Point = Nothing
            Dim HSnapping As Boolean = Nothing
            Dim HSnapLineStart As Point = Nothing
            Dim HSnapLineEnd As Point = Nothing
            Dim XSnapCtl As SnapControl = Nothing
            Dim YSnapCtl As SnapControl = Nothing

            Offset = New Point(_DesignSurface.PointToClient(CType(sender, Control).PointToScreen(e.Location)).X - _ResizeStartMouseLocation.X, _DesignSurface.PointToClient(CType(sender, Control).PointToScreen(e.Location)).Y - _ResizeStartMouseLocation.Y)

            Dim NewLoc As Point = Nothing
            Dim NewSize As Size = Nothing
            Dim SnapOffsetX As Integer = 0
            Dim SnapOffsetY As Integer = 0
            Dim IsSnapX As Boolean = False
            Dim IsSnapY As Boolean = False
            Dim X1, X2, Y1, Y2 As Integer

            If sender Is _TopLeftBox Then
                NewLoc = New Point(_ResizeStartCtlLocation.X + Offset.X, _ResizeStartCtlLocation.Y + Offset.Y)
                NewSize = New Size(_ResizeStartCtlSize.Width - Offset.X, _ResizeStartCtlSize.Height - Offset.Y)
                'Snap Left Edge in X direction
                IsSnapX = FindProximitySnapX(_BoundControl.Parent.PointToScreen(NewLoc).X, _DesignerControls, SnapOffsetX, XSnapCtl)
                If IsSnapX Then
                    NewLoc.X += SnapOffsetX
                    NewSize.Width -= SnapOffsetX

                    VSnapping = True
                    X1 = NewLoc.X - 1
                    X2 = X1
                    If _BoundControl.Parent.PointToScreen(_BoundControl.Location).Y < XSnapCtl.ScreenLoc.Y Then
                        'Bound control above snapped to control
                        Y1 = NewLoc.X
                        Y2 = _BoundControl.Parent.PointToClient(XSnapCtl.ScreenLoc).Y + XSnapCtl.Size.Height
                    Else
                        'Bound control to left of snapped to control
                        Y1 = _BoundControl.Parent.PointToClient(XSnapCtl.ScreenLoc).Y
                        Y2 = NewLoc.Y + NewSize.Height
                    End If
                    VSnapLineStart = New Point(X1, Y1)
                    VSnapLineEnd = New Point(X2, Y2)
                End If
                'Snap Top Edge in Y direction
                IsSnapY = FindProximitySnapY(_BoundControl.Parent.PointToScreen(NewLoc).Y, _DesignerControls, SnapOffsetY, YSnapCtl)
                If IsSnapY Then
                    NewLoc.Y += SnapOffsetY
                    NewSize.Height -= SnapOffsetY

                    HSnapping = True
                    Y1 = NewLoc.Y - 1
                    Y2 = Y1
                    If _BoundControl.Parent.PointToScreen(_BoundControl.Location).X < YSnapCtl.ScreenLoc.X Then
                        'Bound control to left of snapped to control
                        X1 = NewLoc.X
                        X2 = _BoundControl.Parent.PointToClient(YSnapCtl.ScreenLoc).X + YSnapCtl.Size.Width
                    Else
                        'Bound control to left of snapped to control
                        X1 = _BoundControl.Parent.PointToClient(YSnapCtl.ScreenLoc).X
                        X2 = NewLoc.X + NewSize.Width
                    End If
                    HSnapLineStart = New Point(X1, Y1)
                    HSnapLineEnd = New Point(X2, Y2)
                End If

            ElseIf sender Is _TopCenterBox Then
                NewLoc = New Point(_ResizeStartCtlLocation.X, _ResizeStartCtlLocation.Y + Offset.Y)
                NewSize = New Size(_ResizeStartCtlSize.Width, _ResizeStartCtlSize.Height - Offset.Y)

                'Snap Top Edge in Y direction
                IsSnapY = FindProximitySnapY(_BoundControl.Parent.PointToScreen(NewLoc).Y, _DesignerControls, SnapOffsetY, YSnapCtl)
                If IsSnapY Then
                    NewLoc.Y += SnapOffsetY
                    NewSize.Height -= SnapOffsetY

                    HSnapping = True
                    Y1 = NewLoc.Y - 1
                    Y2 = Y1
                    If _BoundControl.Parent.PointToScreen(_BoundControl.Location).X < YSnapCtl.ScreenLoc.X Then
                        'Bound control to left of snapped to control
                        X1 = NewLoc.X
                        X2 = _BoundControl.Parent.PointToClient(YSnapCtl.ScreenLoc).X + YSnapCtl.Size.Width
                    Else
                        'Bound control to left of snapped to control
                        X1 = _BoundControl.Parent.PointToClient(YSnapCtl.ScreenLoc).X
                        X2 = NewLoc.X + NewSize.Width
                    End If
                    HSnapLineStart = New Point(X1, Y1)
                    HSnapLineEnd = New Point(X2, Y2)
                End If
            ElseIf sender Is _TopRightBox Then
                NewLoc = New Point(_ResizeStartCtlLocation.X, _ResizeStartCtlLocation.Y + Offset.Y)
                NewSize = New Size(_ResizeStartCtlSize.Width + Offset.X, _ResizeStartCtlSize.Height - Offset.Y)
                'Snap Right Edge in X direction
                IsSnapX = FindProximitySnapX(_BoundControl.Parent.PointToScreen(NewLoc).X + NewSize.Width, _DesignerControls, SnapOffsetX, XSnapCtl)
                If IsSnapX Then
                    NewSize.Width += SnapOffsetX

                    VSnapping = True
                    X1 = NewLoc.X + NewSize.Width + 1
                    X2 = X1
                    If _BoundControl.Parent.PointToScreen(_BoundControl.Location).Y < XSnapCtl.ScreenLoc.Y Then
                        'Bound control above snapped to control
                        Y1 = NewLoc.X
                        Y2 = _BoundControl.Parent.PointToClient(XSnapCtl.ScreenLoc).Y + XSnapCtl.Size.Height
                    Else
                        'Bound control to left of snapped to control
                        Y1 = _BoundControl.Parent.PointToClient(XSnapCtl.ScreenLoc).Y
                        Y2 = NewLoc.Y + NewSize.Height
                    End If
                    VSnapLineStart = New Point(X1, Y1)
                    VSnapLineEnd = New Point(X2, Y2)
                End If

                'Snap Top Edge in Y direction
                IsSnapY = FindProximitySnapY(_BoundControl.Parent.PointToScreen(NewLoc).Y, _DesignerControls, SnapOffsetY, YSnapCtl)
                If IsSnapY Then
                    NewLoc.Y += SnapOffsetY
                    NewSize.Height -= SnapOffsetY

                    HSnapping = True
                    Y1 = NewLoc.Y - 1
                    Y2 = Y1
                    If _BoundControl.Parent.PointToScreen(_BoundControl.Location).X < YSnapCtl.ScreenLoc.X Then
                        'Bound control to left of snapped to control
                        X1 = NewLoc.X
                        X2 = _BoundControl.Parent.PointToClient(YSnapCtl.ScreenLoc).X + YSnapCtl.Size.Width
                    Else
                        'Bound control to left of snapped to control
                        X1 = _BoundControl.Parent.PointToClient(YSnapCtl.ScreenLoc).X
                        X2 = NewLoc.X + NewSize.Width
                    End If
                    HSnapLineStart = New Point(X1, Y1)
                    HSnapLineEnd = New Point(X2, Y2)
                End If

            ElseIf sender Is _MiddleRightBox Then
                NewLoc = _BoundControl.Location
                NewSize = New Size(_ResizeStartCtlSize.Width + Offset.X, _ResizeStartCtlSize.Height)
                'Snap Right Edge in X direction
                IsSnapX = FindProximitySnapX(_BoundControl.Parent.PointToScreen(NewLoc).X + NewSize.Width, _DesignerControls, SnapOffsetX, XSnapCtl)
                If IsSnapX Then
                    NewSize.Width += SnapOffsetX

                    VSnapping = True
                    X1 = NewLoc.X + NewSize.Width + 1
                    X2 = X1
                    If _BoundControl.Parent.PointToScreen(_BoundControl.Location).Y < XSnapCtl.ScreenLoc.Y Then
                        'Bound control above snapped to control
                        Y1 = NewLoc.X
                        Y2 = _BoundControl.Parent.PointToClient(XSnapCtl.ScreenLoc).Y + XSnapCtl.Size.Height
                    Else
                        'Bound control to left of snapped to control
                        Y1 = _BoundControl.Parent.PointToClient(XSnapCtl.ScreenLoc).Y
                        Y2 = NewLoc.Y + NewSize.Height
                    End If
                    VSnapLineStart = New Point(X1, Y1)
                    VSnapLineEnd = New Point(X2, Y2)
                End If


            ElseIf sender Is _BottomRightBox Then
                NewLoc = _BoundControl.Location
                NewSize = New Size(_ResizeStartCtlSize.Width + Offset.X, _ResizeStartCtlSize.Height + Offset.Y)
                'Snap Right Edge in X direction
                IsSnapX = FindProximitySnapX(_BoundControl.Parent.PointToScreen(NewLoc).X + NewSize.Width, _DesignerControls, SnapOffsetX, XSnapCtl)
                If IsSnapX Then
                    NewSize.Width += SnapOffsetX

                    VSnapping = True
                    X1 = NewLoc.X + NewSize.Width + 1
                    X2 = X1
                    If _BoundControl.Parent.PointToScreen(_BoundControl.Location).Y < XSnapCtl.ScreenLoc.Y Then
                        'Bound control above snapped to control
                        Y1 = NewLoc.X
                        Y2 = _BoundControl.Parent.PointToClient(XSnapCtl.ScreenLoc).Y + XSnapCtl.Size.Height
                    Else
                        'Bound control to left of snapped to control
                        Y1 = _BoundControl.Parent.PointToClient(XSnapCtl.ScreenLoc).Y
                        Y2 = NewLoc.Y + NewSize.Height
                    End If
                    VSnapLineStart = New Point(X1, Y1)
                    VSnapLineEnd = New Point(X2, Y2)
                End If

                'Snap Bottom Edge in Y direction
                IsSnapX = FindProximitySnapY(_BoundControl.Parent.PointToScreen(NewLoc).Y + NewSize.Height, _DesignerControls, SnapOffsetY, YSnapCtl)
                If IsSnapX Then
                    NewSize.Height += SnapOffsetY

                    HSnapping = True
                    Y1 = NewLoc.Y + NewSize.Height + 1
                    Y2 = Y1
                    If _BoundControl.Parent.PointToScreen(_BoundControl.Location).X < YSnapCtl.ScreenLoc.X Then
                        'Bound control to left of snapped to control
                        X1 = NewLoc.X
                        X2 = _BoundControl.Parent.PointToClient(YSnapCtl.ScreenLoc).X + YSnapCtl.Size.Width
                    Else
                        'Bound control to left of snapped to control
                        X1 = _BoundControl.Parent.PointToClient(YSnapCtl.ScreenLoc).X
                        X2 = NewLoc.X + NewSize.Width
                    End If
                    HSnapLineStart = New Point(X1, Y1)
                    HSnapLineEnd = New Point(X2, Y2)
                End If


            ElseIf sender Is _BottomCenterBox Then
                NewLoc = _BoundControl.Location
                NewSize = New Size(_ResizeStartCtlSize.Width, _ResizeStartCtlSize.Height + Offset.Y)
                'Snap Bottom Edge in Y direction
                IsSnapX = FindProximitySnapY(_BoundControl.Parent.PointToScreen(NewLoc).Y + NewSize.Height, _DesignerControls, SnapOffsetY, YSnapCtl)
                If IsSnapX Then
                    NewSize.Height += SnapOffsetY

                    HSnapping = True
                    Y1 = NewLoc.Y + NewSize.Height + 1
                    Y2 = Y1
                    If _BoundControl.Parent.PointToScreen(_BoundControl.Location).X < YSnapCtl.ScreenLoc.X Then
                        'Bound control to left of snapped to control
                        X1 = NewLoc.X
                        X2 = _BoundControl.Parent.PointToClient(YSnapCtl.ScreenLoc).X + YSnapCtl.Size.Width
                    Else
                        'Bound control to left of snapped to control
                        X1 = _BoundControl.Parent.PointToClient(YSnapCtl.ScreenLoc).X
                        X2 = NewLoc.X + NewSize.Width
                    End If
                    HSnapLineStart = New Point(X1, Y1)
                    HSnapLineEnd = New Point(X2, Y2)
                End If


            ElseIf sender Is _BottomLeftBox Then
                NewLoc = New Point(_ResizeStartCtlLocation.X + Offset.X, _ResizeStartCtlLocation.Y)
                NewSize = New Size(_ResizeStartCtlSize.Width - Offset.X, _ResizeStartCtlSize.Height + Offset.Y)
                'Snap Left Edge in X direction
                IsSnapX = FindProximitySnapX(_BoundControl.Parent.PointToScreen(NewLoc).X, _DesignerControls, SnapOffsetX, XSnapCtl)
                If IsSnapX Then
                    NewLoc.X += SnapOffsetX
                    NewSize.Width -= SnapOffsetX

                    VSnapping = True
                    X1 = NewLoc.X - 1
                    X2 = X1
                    If _BoundControl.Parent.PointToScreen(_BoundControl.Location).Y < XSnapCtl.ScreenLoc.Y Then
                        'Bound control above snapped to control
                        Y1 = NewLoc.X
                        Y2 = _BoundControl.Parent.PointToClient(XSnapCtl.ScreenLoc).Y + XSnapCtl.Size.Height
                    Else
                        'Bound control to left of snapped to control
                        Y1 = _BoundControl.Parent.PointToClient(XSnapCtl.ScreenLoc).Y
                        Y2 = NewLoc.Y + NewSize.Height
                    End If
                    VSnapLineStart = New Point(X1, Y1)
                    VSnapLineEnd = New Point(X2, Y2)
                End If
                'Snap Bottom Edge in Y direction
                IsSnapX = FindProximitySnapY(_BoundControl.Parent.PointToScreen(NewLoc).Y + NewSize.Height, _DesignerControls, SnapOffsetY, YSnapCtl)
                If IsSnapX Then
                    NewSize.Height += SnapOffsetY

                    HSnapping = True
                    Y1 = NewLoc.Y + NewSize.Height + 1
                    Y2 = Y1
                    If _BoundControl.Parent.PointToScreen(_BoundControl.Location).X < YSnapCtl.ScreenLoc.X Then
                        'Bound control to left of snapped to control
                        X1 = NewLoc.X
                        X2 = _BoundControl.Parent.PointToClient(YSnapCtl.ScreenLoc).X + YSnapCtl.Size.Width
                    Else
                        'Bound control to left of snapped to control
                        X1 = _BoundControl.Parent.PointToClient(YSnapCtl.ScreenLoc).X
                        X2 = NewLoc.X + NewSize.Width
                    End If
                    HSnapLineStart = New Point(X1, Y1)
                    HSnapLineEnd = New Point(X2, Y2)
                End If

            ElseIf sender Is _MiddleLeftBox Then
                NewLoc = New Point(_ResizeStartCtlLocation.X + Offset.X, _ResizeStartCtlLocation.Y)
                NewSize = New Size(_ResizeStartCtlSize.Width - Offset.X, _ResizeStartCtlSize.Height)
                'Snap Left Edge in X direction
                IsSnapX = FindProximitySnapX(_BoundControl.Parent.PointToScreen(NewLoc).X, _DesignerControls, SnapOffsetX, XSnapCtl)
                If IsSnapX Then
                    NewLoc.X += SnapOffsetX
                    NewSize.Width -= SnapOffsetX

                    VSnapping = True
                    X1 = NewLoc.X - 1
                    X2 = X1
                    If _BoundControl.Parent.PointToScreen(_BoundControl.Location).Y < XSnapCtl.ScreenLoc.Y Then
                        'Bound control above snapped to control
                        Y1 = NewLoc.X
                        Y2 = _BoundControl.Parent.PointToClient(XSnapCtl.ScreenLoc).Y + XSnapCtl.Size.Height
                    Else
                        'Bound control to left of snapped to control
                        Y1 = _BoundControl.Parent.PointToClient(XSnapCtl.ScreenLoc).Y
                        Y2 = NewLoc.Y + NewSize.Height
                    End If
                    VSnapLineStart = New Point(X1, Y1)
                    VSnapLineEnd = New Point(X2, Y2)
                End If

            End If

            _BoundControl.Bounds = New Rectangle(NewLoc, NewSize)

            DrawLayoutGlyphs(VSnapping, VSnapLineStart, VSnapLineEnd, HSnapping, HSnapLineStart, HSnapLineEnd)

        End If
    End Sub

    Private Sub ControlLocationChanged(ByVal sender As Object, ByVal e As System.EventArgs)
        DrawLayoutGlyphs(False, Nothing, Nothing, False, Nothing, Nothing)
    End Sub
    Private Sub ControlSizeChanged(ByVal sender As Object, ByVal e As System.EventArgs)
        DrawLayoutGlyphs(False, Nothing, Nothing, False, Nothing, Nothing)
    End Sub
#End Region
End Class
